home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / sfedit.exe / GETDRVX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-27  |  9.6 KB  |  332 lines

  1. #define NOCOMM
  2. #include <windows.h>
  3. #include <dos.h>
  4. #include <memory.h>
  5. #include "getdrvx.h"
  6.  
  7. #define CDS_SUBST (0x1000)
  8.  
  9. #define DOS3_CDS_SIZE  81
  10. #define DOS4_CDS_SIZE  88
  11. #define CDS_PATH       0x00
  12. #define CDS_FLAGS      0x43
  13. #define CDS_DPB        0x45
  14.  
  15. #define DPB_FATS       8
  16.  
  17. #define MK_FP(seg,ofs)  ((void far *) (((unsigned long)(seg) << 16) | (unsigned)(ofs)))
  18. #define _DS             GetDS()
  19.  
  20. /* Documented Windows functions not declared in WINDOWS.H */
  21. DWORD FAR PASCAL GlobalDosAlloc(DWORD dwBytes);
  22. WORD  FAR PASCAL GlobalDosFree(WORD wSelector);
  23.  
  24. /* Undocumented Windows functions */
  25. VOID FAR PASCAL SetSelectorBase(WORD wSelector, DWORD dwBase);
  26. VOID FAR PASCAL SetSelectorLimit(WORD wSelector, DWORD dwLimit);
  27.  
  28. /* Global Variables */
  29. WORD _wSelector;                // a data selector
  30.  
  31. /* Types */
  32. // DOS list of lists structure (for DOS 3.1 or better)
  33. typedef struct {
  34.     BYTE x[22];                 // (don't care)
  35.     BYTE far* cds;
  36.     BYTE xx[7];                 // (don't care)
  37.     BYTE lastdrive;
  38.     // ... the rest of DOS List of Lists
  39. } DOSLISTS;
  40.  
  41. // DPMI real-mode call structure
  42. typedef struct {
  43.     DWORD edi, esi, ebp, reserved, ebx, edx, ecx, eax;
  44.     WORD  flags, es, ds, fs, gs, ip, cs, sp, ss;
  45. } REALMODECALL;
  46.  
  47.  
  48. int GetDosVersionMajor(void)
  49. {
  50.     int     dosver;
  51.  
  52.     _asm    mov ah, 0x30;
  53.     _asm    int 0x21;
  54.     _asm    mov dosver, ax;
  55.  
  56.     return (BYTE)dosver;
  57. }
  58.  
  59. unsigned GetDS(void)
  60. {
  61.     _asm    mov ax, ds;
  62.     return;                 // return value in AX
  63. }
  64.  
  65.  
  66. /****************************************************************************
  67.     BOOL DPMI_RealModeInt(int intno, REALMODECALL far* r)
  68.  
  69.     PURPOSE: DPMI simulate real-mode interrupt function.  The
  70.     following is an excerpt from the DPMI Specification:
  71.  
  72.     PARAMETERS:
  73.         int   intno             real-mode interrupt to simulate
  74.         REALMODECALL far* r
  75.  
  76.     RETURNS: TRUE if interrupt is successful, FALSE on error
  77.  
  78.     NOTES: The following is an excerpt from INTEL's DPMI specs:
  79.  
  80.       To Call
  81.  
  82.            AX = 0300h
  83.            BL = Interrupt number
  84.            BH = Flags
  85.                 Bit 0  = 1 resets the interrupt controller and A20
  86.                 line
  87.                 Other flags reserved and must be 0
  88.            CX =  Number of  words to  copy from  protected mode to
  89.                 real-mode stack
  90.            ES:(E)DI = Selector:Offset of real-mode call structure
  91.  
  92.       Returns
  93.  
  94.            If function was successful:
  95.            Carry flag is clear.
  96.            ES:(E)DI =  Selector:Offset of modified real-mode call
  97.                 structure
  98.  
  99.            If function was not successful:
  100.            Carry flag is set.
  101. ****************************************************************************/
  102. BOOL DPMI_RealModeInt(int intno, REALMODECALL far* r)
  103. {
  104.     intno &= 0x00FF;        // reset high byte (flags)
  105.  
  106.     _asm {
  107.         push    di
  108.         mov     bx, intno   // flags | real-mode interrupt to call
  109.         mov     cx, 0       // don't copy anything from protected mode stack
  110.         les     di, r       // es:di -> real-mode call structure
  111.         mov     ax, 0x0300  // DPMI simulate real-mode interrupt function
  112.         int     0x31
  113.         pop     di
  114.         jc      error
  115.     }
  116.     return  TRUE;
  117.  
  118. error:
  119.     return  FALSE;
  120. }
  121.  
  122. /****************************************************************************
  123.     BYTE far* PMODE_ADDR(WORD wSel, BYTE far* RMODE_ADDR)
  124.  
  125.     PURPOSE: Get the Current Directory Structure
  126.  
  127.     PARAMETERS:
  128.         WORD wSel               A valid selector
  129.         BYTE far* RMODE_ADDR    A real mode address
  130.  
  131.     RETURNS: a protected-mode address of RMODE_ADDR
  132.  
  133.     NOTES: The base address of selector wSel is set to the segment of
  134.     RMODE_ADDR.
  135. *****************************************************************************/
  136. BYTE far* PMODE_ADDR(WORD wSel, BYTE far* RMODE_ADDR)
  137. {
  138.     SetSelectorBase(wSel, (DWORD) FP_SEG(RMODE_ADDR) << 4);
  139.     return  MK_FP(wSel, FP_OFF(RMODE_ADDR));
  140. }
  141.  
  142. /****************************************************************************
  143.     BYTE far* GetCDS(int nDrive)
  144.  
  145.     PURPOSE: Get the Current Directory Structure
  146.  
  147.     PARAMETERS: int nDrive          The drive to retrieve
  148.  
  149.     RETURNS: a real-mode pointer to the Current Directory Structure of
  150.     drive nDrive.
  151. *****************************************************************************/
  152. BYTE far* GetCDS(int nDrive)
  153. {
  154.     DOSLISTS far*   doslists;
  155.     REALMODECALL    r;
  156.  
  157.     // Get DOS list of lists (INT 21h, Function 52h)
  158.     _fmemset(&r, 0, sizeof(REALMODECALL));
  159.     r.eax = 0x5200;
  160.     if (!DPMI_RealModeInt(0x21, &r))
  161.         return  NULL;
  162.  
  163.     // Pointer to DOS list of lists is returned in ES:BX
  164.     doslists = (DOSLISTS far*)
  165.         PMODE_ADDR( _wSelector, MK_FP(r.es, LOWORD(r.ebx)) );
  166.  
  167.     if (GetDosVersionMajor() < 4)
  168.        return   doslists->cds + (nDrive * DOS3_CDS_SIZE);
  169.     else
  170.        return   doslists->cds + (nDrive * DOS4_CDS_SIZE);
  171. }
  172.  
  173. /****************************************************************************
  174.     BOOL isCDROM(int nDrive)
  175.  
  176.     PURPOSE: Tests if nDrive is a CD ROM drive
  177.  
  178.     PARAMETERS: int nDrive          The drive to test
  179.  
  180.     RETURNS: TRUE if nDrive is a CD ROM
  181.  *****************************************************************************/
  182. BOOL isCDROM(int nDrive)
  183. {
  184.     WORD     saveAX, saveBX;
  185.  
  186.     _asm     mov cx, nDrive;
  187.     _asm     mov ax, 0x150B;
  188.     _asm     int 0x2F;
  189.     _asm     mov saveAX, ax;
  190.     _asm     mov saveBX, bx;
  191.  
  192.     return   saveBX == 0xADAD && saveAX != 0;
  193. }
  194.  
  195.  
  196. /****************************************************************************
  197.     BOOL isSubstDrive(int nDrive)
  198.  
  199.     PURPOSE: Tests for drives created using the DOS SUBST command
  200.  
  201.     PARAMETERS: int nDrive          The drive to test
  202.  
  203.     RETURNS: TRUE if nDrive is a SUBST drive
  204. *****************************************************************************/
  205. BOOL isSubstDrive(int nDrive)
  206. {
  207.     BYTE far*   cds;        // Current Directory Structure
  208.     WORD        cds_flags;
  209.  
  210.     cds = PMODE_ADDR(_wSelector, GetCDS(nDrive));
  211.     cds_flags = *(WORD far*)(cds+CDS_FLAGS);
  212.     if (cds_flags &  (CDS_SUBST))
  213.         return  TRUE;
  214.  
  215.     return  FALSE;
  216. }
  217.  
  218. /****************************************************************************
  219.     BOOL isRamDrive(int nDrive)
  220.  
  221.     PURPOSE: Tests for Ram drives
  222.  
  223.     PARAMETERS: int nDrive          The drive to test
  224.  
  225.     RETURNS: TRUE if nDrive is a ram drive
  226.  
  227.     NOTES: This function tests to see if the drive has only one FAT.  It
  228.     is assumed that if this is true, then the drive must be a RAM drive.
  229. *****************************************************************************/
  230. BOOL isRamDrive(int nDrive)
  231. {
  232.     BYTE far*   cds;    // Current Directory Structure
  233.     BYTE far*   dpb;    // Drive Parameter Block
  234.  
  235.     cds = PMODE_ADDR(_wSelector, GetCDS(nDrive));
  236.  
  237.     dpb = *(BYTE far* far*)(cds+CDS_DPB);
  238.     dpb = PMODE_ADDR(_wSelector, dpb);
  239.  
  240.     if (*(dpb+DPB_FATS) == 1)
  241.         return  TRUE;
  242.  
  243.     return  FALSE;
  244. }
  245.  
  246. /****************************************************************************
  247.     WORD FAR PASCAL GetDriveTypeX(int nDrive)
  248.  
  249.     PURPOSE: Determines drive type
  250.  
  251.     PARAMETERS:
  252.         int   nDrive            The drive number. 0 = A:, 1 = B:,
  253.                                 2 = C:, 3 = D:, ...
  254.     RETURNS:
  255.         DRIVE_UNKNOWN           Unknown drive type
  256.         DRIVE_NOTEXIST          Drive does not exist
  257.         DRIVE_REMOVE            Removable (floppy) drive
  258.         DRIVE_FIXED             Fixed (hard) drive
  259.         DRIVE_REMOTE            Remote (network) drive
  260.         DRIVE_CDROM             CD ROM drive
  261.         DRIVE_RAM               Ram drive
  262.         DRIVE_SUBST             SUBST drive
  263. *****************************************************************************/
  264. WORD FAR PASCAL GetDriveTypeX(int nDrive)
  265. {
  266.     WORD    wDriveType;
  267.  
  268.     // Get a new selector, using the current DS as the prototype
  269.     _wSelector = AllocSelector(_DS);
  270.     SetSelectorLimit(_wSelector, 0xFFFF);
  271.  
  272.     wDriveType = GetDriveType(nDrive);
  273.  
  274.     if (isCDROM(nDrive))
  275.         wDriveType = DRIVE_CDROM;
  276.     else
  277.     if (wDriveType != DRIVE_REMOTE && isSubstDrive(nDrive))
  278.         wDriveType = DRIVE_SUBST;
  279.     else
  280.     if (isRamDrive(nDrive))
  281.         wDriveType = DRIVE_RAM;
  282.  
  283.     FreeSelector(_wSelector);
  284.     return  wDriveType;
  285. }
  286.  
  287. /****************************************************************************
  288.     BOOL FAR PASCAL GetCanonicalPath(LPSTR lpszRelPath, LPSTR lpszTruePath)
  289.  
  290.     PURPOSE: Resolve path string to canonical path string
  291.  
  292.     PARAMETERS:
  293.         LPSTR   lpszRelPath     Relative path string or directory name
  294.         LPSTR   lpszTruePath    Destination for canonical fully qualified
  295.                                 path
  296.     RETURNS:
  297.         TRUE if successful
  298. *****************************************************************************/
  299. BOOL FAR PASCAL GetCanonicalPath(LPSTR lpszRelPath, LPSTR lpszTruePath)
  300. {
  301.     BOOL        retval;
  302.     DWORD       dw;
  303.     WORD        wSelector;
  304.     WORD        wSegment;
  305.     LPSTR       lpszDosBuf;
  306.     REALMODECALL    r;
  307.  
  308.     dw = GlobalDosAlloc(128);
  309.     if (dw == NULL)
  310.         return FALSE;
  311.  
  312.     wSelector = LOWORD(dw);
  313.     wSegment  = HIWORD(dw);
  314.  
  315.     lpszDosBuf = MK_FP(wSelector, 0);
  316.     _fmemcpy(lpszDosBuf, lpszRelPath, 128);
  317.  
  318.     r.eax = 0x6000;
  319.     r.ds  = wSegment;
  320.     r.esi = 0;
  321.     r.es  = wSegment;
  322.     r.edi = 0;
  323.  
  324.     retval = DPMI_RealModeInt(0x21, &r);
  325.  
  326.     _fmemcpy(lpszTruePath, lpszDosBuf, 128);
  327.     GlobalDosFree(wSelector);
  328.  
  329.     return  retval;
  330. }
  331.  
  332.